﻿using com.iot.core.boot;
using com.iot.core.boot.configuration;
using com.iot.core.data;
using com.iot.core.exception;
using com.iot.core.infrastructure;
using com.iot.core.manager.id;
using com.iot.core.util;
using com.iot.ht.Controllers.htsoft.data;
using com.iot.ht.Controllers.htsoft.service;
using com.iot.ht.Controllers.httask.data;
using Microsoft.EntityFrameworkCore;
using Org.BouncyCastle.Pqc.Crypto.Lms;
using System.Linq.Dynamic;
using System.Reflection;
using System.Text;

namespace com.iot.ht.Controllers.httask.service
{
    public class HtTaskService : BackgroundService
    {
        ILogger<HtTaskService> log;
         
        IRepository<HtTaskApp> baseMapper;
        int RunTimes = 0;
        List<HtTaskLog> lstHtSoftLog=new List<HtTaskLog>();


        ParallelOptions parallelOptions ;
        HtSoftCfg htSoftCfg;
        IWebHostEnvironment environment;


        public List<HtTaskAppStateDto> Apps { get; private set; } = null;
        
        public List<HtTaskApp> HtTaskApps
        {
            get
            {
                return Apps.Select(a => a.HtTaskApp).ToList();
            }
        }


        public HtTaskService(ILogger<HtTaskService> log )
        {
            this.log = log;
            Singleton<HtTaskService>.Instance = this;
            
        }
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
          
            while (!stoppingToken.IsCancellationRequested)
            {
                try {

                    
                    if (RunTimes == 0)
                    {
                        await Task.Delay(3000);//延迟启动 
                        parallelOptions = new ParallelOptions
                        {
                            CancellationToken = stoppingToken,
                            MaxDegreeOfParallelism = 2,

                        };
                        htSoftCfg = Singleton<AppSettings>.Instance.Get<HtSoftCfg>();
                        //要手动创建工厂
                        var fact = EngineContext.Current.Resolve < IDbContextFactory<IotDbContext>>();
                        environment = EngineContext.Current.Resolve< IWebHostEnvironment >();

                        var db = fact.CreateDbContext();
                        baseMapper = new Repository<HtTaskApp>(db);


                        log.LogInformation($"主任务启动....");                         
                       
                    }

                    if (Apps == null)
                    {
                        LoadDb();
                    }

                    for(var i = 0; i < Apps.Count; i++)
                    {
                        if (!Apps[i].Started && Apps[i].NeedStart)
                        {
                            try
                            {
                                 await StartApp(Apps[i]);
                            }
                            catch (Exception ex)
                            {
                                log.LogError("启动错误：" + ex.Message ?? "");
                            }
                        }
                    }

                    for (var i = 0; i < Apps.Count; i++)
                    {
                        var mm = Apps[i];
                        if (!mm.Started)
                        {
                            continue;
                        }
                        if (mm.HtAbstractTask == null)
                        {
                            continue;
                        }
                        await mm.HtAbstractTask.ExecuteAsync(stoppingToken);
                    }
                        
                    

                    RunTimes++;
                    SaveLog();
                    await Task.Delay(1000);
                }
                catch(Exception ex2)
                {
                    log.LogError("主任务ExecuteAsync：" + ex2.Message ?? "");
                } 
            }
           
            log.LogInformation("主任务停止"); 
        }

        async Task ExecuteTaskAsync(HtTaskAppStateDto mm, CancellationToken stoppingToken)
        {
            if (!mm.Started)
            {
                return;
            }
            if (mm.HtAbstractTask == null)
            {
                return;
            }
            await mm.HtAbstractTask.ExecuteAsync(stoppingToken);    
        }
        void LoadDb()
        {
            var l = new List<HtTaskAppStateDto>();
            baseMapper.GetAll()
                .AsNoTracking()
                .Where(a => a.HostId == htSoftCfg.HostId)
                .OrderBy(a => a.Sortno)
                .ToList()
                .ForEach(m =>
                {
                    var mm = CreateHtTaskAppStateDto(m);
                    l.Add(mm);

                });
            Apps = l;
        }
        HtTaskAppStateDto CreateHtTaskAppStateDto(HtTaskApp mm)
        {
            var m = new HtTaskAppStateDto
            {
                Id = mm.Id,
                Name = mm.Name,
                 
                HtTaskApp = mm,
                Started = false,
                LstDt = DateTime.Parse("2020-01-01"),
                LstMsg = "",
                LstResult = false,
                HtAbstractTask=null,
                NeedStart=mm.AutoStart
            };
            return m;
        }


        async Task<MyApiResult> StartApp(HtTaskAppStateDto mm)
        {
            var r = new MyApiResult();
            if (mm.Started)
            {
                return r;
            }
            if (!File.Exists(mm.HtTaskApp.DllPath))
            {
                r.Code = 1;
                r.Msg = "启动失败：" + "文件不存在";
                AddLog(mm.HtTaskApp, r.Msg);
                return r;
            }
            var buff = File.ReadAllBytes(mm.HtTaskApp.DllPath);
            var asm = Assembly.Load(buff);
            var t = asm.GetType(mm.HtTaskApp.ClsFullName);
            if (t == null)
            {
                r.Code = 1;
                r.Msg = "启动失败：" + "类型不存在";
                AddLog(mm.HtTaskApp, r.Msg);
                return r;
                
            }
            mm.HtAbstractTask=Activator.CreateInstance(t) as HtAbstractTask;
            mm.HtAbstractTask.HtTaskAppStateDto = mm;

            mm.LstResult = true;
            mm.LstMsg = "";
            mm.LstDt = DateTime.Parse("2000-01-01");
            mm.Started = true;
            r.Msg = "启动成功";
            AddLog(mm.HtTaskApp, r.Msg);
            return r;
        }

        async Task<MyApiResult> StopApp(HtTaskAppStateDto mm)
        {
            var r = new MyApiResult();
            mm.Started = false;
            mm.LstResult = false;
            mm.LstMsg = "";
            mm.LstDt = DateTime.Parse("2000-01-01");
            AddLog(mm.HtTaskApp, "停止：" + r.Msg);

            return r;
        }


        #region 数据操作
        public int Insert(HtTaskApp mm)
        {

            var mold = Apps.Where(a => a.Id == mm.Id).FirstOrDefault();
            if (mold != null)
            {
                throw new MyException("编号重复");
            }
            mold = Apps.Where(a => a.Name == mm.Name).FirstOrDefault();
            if (mold != null)
            {
                throw new MyException("名称重复");
            }
            mm.HostId = htSoftCfg.HostId;
            baseMapper.Insert(mm, true);
            var r = baseMapper.SaveChagnes();
            baseMapper.DB.ChangeTracker.Clear();
            var mdto = CreateHtTaskAppStateDto(mm);
            Apps.Add(mdto);
            return r;
        }
        public int Update(HtTaskApp mm)
        {
            var mold = Apps.Where(a => a.Id == mm.Id).FirstOrDefault();
            if (mold == null)
            {
                throw new MyException("数据错误");
            }

            var moldApp = Apps.Where(a => a.Id == mm.Id).FirstOrDefault();
            if (moldApp.Started)
            {
                throw new MyException("正在运行，不能修改");
            }

            if (mold.Name != mm.Name)
            {

                mold = Apps.Where(a => a.Name == mm.Name).FirstOrDefault();
                if (mold != null)
                {
                    throw new MyException("名称重复");
                }
            }
            baseMapper.Update(mm, true);
            var r = baseMapper.SaveChagnes();
            baseMapper.DB.ChangeTracker.Clear();
            moldApp.Name = mm.Name;
            moldApp.HtTaskApp = mm;
            return r;
        }

        public int Delete(BaseQto mm)
        {

            var moldApp = Apps.Where(a => a.Id == mm.Id).FirstOrDefault();
            if (moldApp.Started)
            {
                throw new MyException("正在运行，不能删除");
            }

            baseMapper.Delete(moldApp.HtTaskApp);
            baseMapper.SaveChagnes();
            baseMapper.DB.ChangeTracker.Clear();
            Apps.Remove(moldApp);
            return 1;
        }

        public async Task<int> StartSingleApp(BaseQto mm)
        {
            var mold = Apps.Where(a => a.Id == mm.Id).FirstOrDefault();
            mold.NeedStart = true;
            await Task.Delay(2000);
            return 1;
        }
        public int StopSingleApp(BaseQto mm)
        {
            var mold = Apps.Where(a => a.Id == mm.Id).FirstOrDefault();
            mold.NeedStart = false;
            StopApp(mold);
            return 1;
        }
       
        #endregion


        #region 日志
        public void AddLog(string msg)
        {
            lock (lstHtSoftLog)
            {
                var m = new HtTaskLog
                {
                    Id = HtIdManager.Current.NextLong(),
                    CrtDt = DateTime.Now,
                    HostId = htSoftCfg.HostId,
                    HttaskappId = 0,
                    HttaskappName = "主程序",
                    Msg = msg
                };
                lstHtSoftLog.Add(m);
            }
            
        }

        public void AddLog(HtTaskApp mm, string msg)
        {
            lock (lstHtSoftLog)
            {
                var m = new HtTaskLog
                {
                    Id = HtIdManager.Current.NextLong(),
                    CrtDt = DateTime.Now,
                    HostId = htSoftCfg.HostId,
                    HttaskappId = mm.Id,
                    HttaskappName = mm.Name,
                    Msg = msg
                };
                lstHtSoftLog.Add(m);
            }
               
        }
        void SaveLog()
        {
            if (lstHtSoftLog.Count == 0)
            {
                return;
            }
            baseMapper.DB.AddRange(lstHtSoftLog);
            baseMapper.SaveChagnes();
            lstHtSoftLog.Clear();
        }

        void DeleteLog()
        {
            var tid = HtIdManager.Current.DateToLongID(DateTime.Now.Date.AddDays(-5));
            var sql = $"delete from HtTaskLog where  id<{tid};select 1 as id,'a' as Name;";
            baseMapper.QueryToList<IdNameDto>(sql, 30);


        }
        #endregion


        #region 文件操作
        public async Task SaveRunFileAsync(HtTaskAppStateDto mm,string key,string data)
        {
            await FileUtil.SaveAsync("task/"+mm.Id.ToString(), key + ".txt", data);　
        }
        public async Task<string> GetRunFile(HtTaskAppStateDto mm, string key)
        {
            return await FileUtil.GetAsync("task/" + mm.Id.ToString(), key + ".txt"　);
        }
        #endregion 文件操作


        #region 短信
        public async Task SendSms(string SmsMobiles,string msg)
        {
            Sms sms = null;
            var clsName = "com.iot.ht.Controllers.htsoft.service.Sms" + htSoftCfg.SmsLx;
            var type = Type.GetType(clsName);
            if (type != null)
            {
                sms = Activator.CreateInstance(type) as Sms;
                sms.SmsCfg = htSoftCfg.SmsCfg;
            }
          
            var rmsg = await sms.SendAsync(SmsMobiles, new List<string> { msg });
            AddLog("发送短信：" + rmsg);
        }
        #endregion

    }
}
